<template>
  <div class="input-panel">
    <a-form-model
      :rules="rules"
      ref="inputPanel"
      :model="formModel"
      :label-col="labelCol"
      :wrapper-col="wrapperCol"
    >
      <div class="input-panel-item" v-for="item in config" :key="item.title">
        <template
          v-if="!item.actionType || item.actionType.includes(actionType)"
        >
          <div class="input-panel-title">
            <h2>
              {{ item.title }}
              <a-button
                type="primary"
                v-if="item.titleAsideButtonText"
                @click="
                  (e) => onTitlePartButtonClick(e, item.titleAsideButtonOnClick)
                "
              >
                {{ item.titleAsideButtonText }}</a-button
              >
            </h2>
          </div>
          <div class="input-panel-content">
            <a-row v-if="!item.slotName">
              <template v-for="input in item.inputs">
                <a-col
                  :span="item.span ? item.span : span"
                  :key="input.inputName"
                  v-if="
                    !input.actionType || input.actionType.includes(actionType)
                  "
                >
                  <div class="input-panel-content-item">
                    <a-form-model-item
                      :label="input.label"
                      :prop="input.inputName"
                      :label-col="input.labelCol"
                      :wrapper-col="input.wrapperCol"
                    >
                      <a-input
                        v-model="formModel[input.inputName]"
                        :placeholder="`请输入${input.label}`"
                        :disabled="
                          actionType === 'preview' ? true : input.disabled
                        "
                        v-if="!input.type"
                        @change="(e) => onChange(e, input.onChange)"
                      />
                      <a-textarea
                        v-model="formModel[input.inputName]"
                        :placeholder="`请输入${input.label}`"
                        :disabled="
                          actionType === 'preview' ? true : input.disabled
                        "
                        v-if="input.type === 'textarea' "
                        @change="(e) => onChange(e, input.onChange)"
                      />
                      <a-date-picker
                        v-model="formModel[input.inputName]"
                        :placeholder="`请输入${input.label}`"
                        :disabled="actionType === 'preview'"
                        :show-time="input.format ? true : false"
                        :format="input.format ? input.format : ''"
                        :valueFormat="
                          input.format ? input.format : 'YYYY-MM-DD'
                        "
                        v-if="input.type === 'date'"
                        @change="(e) => onChange(e, input.onChange)"
                      />
                      <a-select
                        v-model="formModel[input.inputName]"
                        :placeholder="`请选择${input.label}`"
                        v-if="input.type === 'select'"
                        @change="(e) => onChange(e, input.onChange)"
                        :disabled="
                          actionType === 'preview' ? true : input.disabled
                        "
                      >
                        <a-select-option
                          v-for="opt in selectOptions[input.inputName]"
                          :key="opt.value"
                          :value="opt.value"
                        >
                          {{ opt.text }}
                        </a-select-option>
                      </a-select>
                      <a-upload
                        v-if="input.type === 'uploadFile'"
                        @change="(e) => onChange(e, input.onChange)"
                        :data="input.params"
                        :action="input.uploadUrl"
                        :headers="headers"
                        :fileList="formModel[input.inputName]"
                        :disabled="actionType === 'preview'"
                        :remove="(e) => handleRemove(e, input.onChange)"
                      >
                        <a-button
                          :disabled="
                            actionType === 'preview' ||
                              formModel[input.inputName].length >= input.maxNum
                          "
                        >
                          <a-icon type="upload" /> 上传
                        </a-button>
                      </a-upload>
                      <a-cascader
                        v-if="input.type === 'cascader'"
                        @change="(e) => onChange(e, input.onChange)"
                        :options="options"
                        placeholder="Please select"
                      />
                      <!-- <template v-for="sItem in input.siblings">
                        <a-select
                        v-model="formModel[sItem.inputName]"
                        :placeholder="`请选择${sItem.label}`"
                        v-if="sItem.type === 'select'"
                        @change="(e) => onChange(e,sItem.onChange)"
                        :disabled = "actionType==='preview'?true:sItem.disabled"
                        :key="sItem.inputName"
                      >
                        <a-select-option
                          v-for="opt in (selectOptions)[sItem.inputName]"
                          :key="opt.value"
                          :value="opt.value"
                        >
                          {{ opt.text }}
                        </a-select-option>
                      </a-select>
                      </template> -->
                    </a-form-model-item>
                  </div>
                </a-col>
              </template>
            </a-row>
            <slot
              :name="item.slotName"
              :formModel="formModel"
              :apiData="apiData"
              v-else
            ></slot>
          </div>
        </template>
      </div>
    </a-form-model>
  </div>
</template>

<script>
import inputConfigInit from "./mixins";
import { getApi, postApi } from "../../services/autoApi";
import { CODE_SUCCESS } from "../../utils/consts";
import { getAuthorizationHeader } from "@/utils/request";

const formModel = {};
const formModelHooks = {};
export default {
  name: "inputPanel",
  data() {
    return {
      formModel,
      formModelHooks,
      rules: {},
      headers: {},
      recordId: "",
      pageId: "",
      fileList: [],
      selectOptions: {},
      apiData: {},
      submitted: false
    };
  },
  mixins: [inputConfigInit],

  // 解决首次进入时watch 不会被触发
  created() {
    this.headers = getAuthorizationHeader();
    this.init();
  },
  watch: {
    visible(val) {
      if (val) {
        this.init();
      }
    }
  },
  props: {
    actionType: {
      type: String,
      default() {
        return "add";
      }
    },
    actionUrls: {
      type: Object,
      default() {
        return {
          add: "",
          update: "",
          query: ""
        };
      }
    },
    disabled: {
      type: Boolean,
      default() {
        return false;
      }
    },
    config: {
      type: Array,
      default() {
        return [];
      }
    },
    span: {
      type: Number,
      default() {
        return 8;
      }
    },
    labelCol: {
      type: Object,
      default() {
        return { span: 8 };
      }
    },
    wrapperCol: {
      type: Object,
      default() {
        return { span: 14 };
      }
    },
    visible: {
      type: Boolean
    }
  },
  computed: {
    updateAndQueryId() {
      return this.actionUrls.updateAndQueryIndex || "workId";
    }
  },
  methods: {
    async handleRecord() {
      if (this.submitted) return;
      let flag = false;
      const formModelHookKeys = Object.keys(this.formModelHooks);
      const { actionType } = this;
      this.submitted = true;
      if (actionType === "update") {
        this.formModel[this.updateAndQueryId] = this.recordId;
      }
      Array.prototype.forEach.call(formModelHookKeys, (item) => {
        (0, this.formModelHooks)[item]?.beforeSubmit?.call(
          this,
          item,
          actionType
        );
      });
      await postApi((0, this.actionUrls)[actionType], this.formModel).then(
        (res) => {
          const { code, message } = res.data;
          if (code === CODE_SUCCESS) {
            this.$message.success(message);
            this.$emit("notifyChange");
            flag = true;
            return;
          }
          this.resetSubmit();
          Array.prototype.forEach.call(formModelHookKeys, (item) => {
            (0, this.formModelHooks)[item]?.afterError?.call(
              this,
              res.data,
              item
            );
          });
          this.$message.error(message);
        }
      );
      return flag;
    },
    async getRecords(record) {
      this.recordId = record[this.updateAndQueryId];
      const params = {};
      params[this.updateAndQueryId] = this.recordId;
      await getApi(this.actionUrls.query, params).then((res) => {
        const { data, code, message } = res.data;
        if (code !== CODE_SUCCESS) {
          this.$message.error(message);
          return;
        }
        this.apiData = { ...data };
        const recordKeys = Object.keys(data);
        Array.prototype.forEach.call(recordKeys, (item) => {
          const des = Object.getOwnPropertyDescriptor(this.formModel, item);
          if (des) {
            (0, this.formModel)[item] = data[item];
            (0, this.formModelHooks)[item]?.afterApiEach?.call(
              this,
              data,
              item
            );
          }
        });
      });
    },
    resetField() {
      this.$refs.inputPanel.resetFields();
      this.resetRecordId();
      this.resetApiData();
      this.resetSubmit();
    },
    resetRecordId() {
      this.recordId = "";
    },
    resetApiData() {
      this.apiData = {};
    },
    resetSubmit() {
      this.submitted = false;
    },
    updateSubmit() {
      this.submitted = true;
    },
    resetApiData() {
      this.apiData = {};
    },
    resetSubmit() {
      this.submitted = false;
    },
    updateSubmit() {
      this.submitted = true;
    },
    formValidate() {
      let flag = true;
      this.$refs.inputPanel.validate((valid) => {
        flag = valid;
        this.resetSubmit();
      });
      return flag;
    },
    clearValidate() {
      this.$refs.inputPanel.clearValidate();
    },
    onChange(e, changeEvent) {
      console.log(e);
      if (!changeEvent) return;
      changeEvent.call(this, e);
    },
    onTitlePartButtonClick(e, clickEvent) {
      if (!clickEvent) return;
      clickEvent.call(this, e);
    },
    beforeUpload(e, beforeUploadEvent) {
      if (!beforeUploadEvent) return;
      beforeUploadEvent.call(this, e);
    },
    beforeRemove(e, beforeRemoveEvent) {
      if (!beforeRemoveEvent) return;
      beforeRemoveEvent.call(this, e);
    },
    handleRemove(e, handleRemoveEvent) {
      if (!handleRemoveEvent) return;
      handleRemoveEvent.call(this, e);
    },
    customRequest(e, cusReq) {
      if (!cusReq) return;
      cusReq.call(this, e);
    },
    updateFormModel(key, val) {
      (0, this.formModel)[key] = val;
    }
  }
};
</script>

<style lang="less" scoped>
.input-panel {
  background: white;
  padding: 0 2rem;
}
.input-panel-item:not(:first-child) {
  padding-top: 1rem;
}
.input-panel-item:not(:last-child) {
  border-bottom: 0.1rem solid rgb(143, 141, 141);
}
</style>
>
